mod context;
mod jrebel;
mod license_client;
mod license_server;

use axum::http::StatusCode;
use axum::response::{IntoResponse, Response};
use axum::{serve, Router};
use std::env;
use std::time::SystemTime;
use tower_http::services::ServeDir;
use tracing::metadata::LevelFilter;
use tracing_subscriber::layer::SubscriberExt;
use tracing_subscriber::util::SubscriberInitExt;
use tracing_subscriber::{fmt, EnvFilter};

pub type AppResult<T> =Result<T, AppError>;
#[tokio::main]
async fn main()->AppResult< ()> {
    // 只有注册 subscriber 后， 才能在控制台上看到日志输出
    let env_filter = EnvFilter::builder().with_env_var("LOG_LEVEL")
        .with_default_directive(LevelFilter::INFO.into())
        .parse("")?;
    tracing_subscriber::registry()
        .with(fmt::layer()
            .with_line_number( true)
            .with_thread_names(true)
            .compact())
        .with(env_filter)
        .init();
    context::agent::init().await.expect("代理初始化失败");
   let mut app = Router::new()
        .fallback_service( ServeDir::new("assets"));
    app = license_client::registry(app);
    app = license_server::registry(app);
    app = jrebel::registry(app);
    let port = match env::var("PORT") {
        Ok(port) => {
            port
        }
        Err(_) => {
            "10086".to_string()
        }
    };
    let listener = tokio::net::TcpListener::bind(format!("0.0.0.0:{}", port)).await?;
    println!("binding port:{}",listener.local_addr()?.port() );
    serve(listener, app).await?;
    Ok(())
}
pub fn get_timestamp()->u128 {
    SystemTime::now().duration_since(SystemTime::UNIX_EPOCH).unwrap().as_millis()
}
pub fn get_random_string<const N: usize>()->AppResult< String> {
    let mut bytes= [0u8;N];
    openssl::rand::rand_bytes(&mut bytes)?;
    let string = hex::encode(&bytes);
    Ok(string.split_at(N / 2).0.to_string())
}
#[derive(Debug)]
pub struct AppError(anyhow::Error);
impl IntoResponse for AppError {
    fn into_response(self) -> Response {
        (
            StatusCode::INTERNAL_SERVER_ERROR,
            format!("Something went wrong: {}", self.0),
        )
            .into_response()
    }
}
impl<E> From<E> for AppError
where
    E: Into<anyhow::Error>,
{
    fn from(err: E) -> Self {
        Self(err.into())
    }
}